let target = {
  a: 1,
  b: 2,
  c: 3,
  b: {
    e: 4,
    f: 5,
    g: 6,
    h: {
      i: 7,
      j: 8
    }
  },
  k: new Date()
}
// 只考虑对象类型
function shallowCopy (obj) {
  if (typeof obj !== 'object') return
  let newObj = obj instanceof Array ? [] : {}
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key]
    }
  }
  return newObj
}
// console.log(shallowCopy(obj))

// 深拷贝 不考虑内置对象和函数
function SimpleDeepClone (obj) {
  if (typeof obj !== 'object') return
  let newObj = obj instanceof Array ? [] : {}
  for (let i in obj) {
    if (typeof obj[i] !== 'object') {
      newObj[i] = obj[i]
    } else {
      newObj[i] = SimpleDeepClone(obj[i])
    }
  }
  return newObj
}
// console.log(SimpleDeepClone(target))

// 深拷贝 考虑了内置对象以及函数，解决了循环引用的问题
const isObject = (target) => (typeof target === 'object' || typeof target === 'function')
function deepClone (target, map = new WeakMap()) {
  if (map.get(target)) {
    return target
  }
  let constructor = target.constructor
  if (/^(RegExp|Date)$/i.test(constructor.name)) {
    return new constructor(target)
  }
  if (isObject(target)) {
    map.set(target, true)
    const cloneTarget = Array.isArray() ? [] : {}
    for (let prop in target) {
      if (target.hasOwnProperty(prop)) {
        cloneTarget[prop] = deepClone(target[prop], map)
      }
    }
    return cloneTarget
  } else {
    return target
  }
}
console.log(deepClone(target))